Bask

Shanghai Based Android Engineer currently develop Payment systems at Ctrip

👨‍🔧‍

Android Hybrid 框架搭建

By Bask on null

This post is over a year old. Some of the content may be out of date.

Hybrid开发顾名思义,就是混合式编程。Android端的Hybrid开发有两种形式,一种为H5直连加载Bridge与Native交互;还有一种则为将Web端代码打入apk安装包中。这两种本质上都是相同的,都是JS和Java或者说class文件交互,而交互的桥梁在Android端其实已经被谷歌封装好,在原生提供的WebView中。主要涉及到两个方法addJavascriptInterface(Object object, String name)loadUrl(String url)。下面我们讲一下这两个方法主要的功能与用法:

期间插一句题外话,为了更好的调试方便,在自己Debug环境下可以设置webview debug eable WebView.setWebContentsDebuggingEnabled(true);在调试期间可以在手机与电脑连接的状态下,在Chrome上访问 chrome://inspect查看App上已打开并且可调试的WebView。

JavascriptInterface

JavascriptInterface顾名思义就是Js的一个接口,定义这样的一个接口就可以让JS访问这个对象。在Android的原生WebView上提供了方法addJavascriptInterface(Object object, String name),这个方法主要是在WebView的window上绑定一个对象,对象名字为name,对象中的内容为object。object为一个包含有 @JavascriptInterface 方法的类,例如:

public class JSTestInterface {

    @JavascriptInterface
    public String getSomethingTest() {
        return "somethingTest";
    }
}

添加JSTestInterface的样例代码为

webView.addJavascriptInterface(new JSTestInterface(), "JSTestInterface");

我们可以看到直接new一个JSTestInterface类的对象,再添加一个“JSTestInterface”标记就可以给Android WebView的window上添加一个接口了,而在Js端调动方法为:

var responseString = window.JSTestInterface.getSomethingTest()

这样就可以获取由Native端提供的字符串。

//TODO调试

可以看出,这是JS调用Native同步返回结果,一般适用于获取一些静态变量的值,比如当前App的版本号、App的AppID等信息,但是如果从Native端异步获取就不能这么调用了。

loadUrl调用JS方法

前文讲到Native异步回调的问题,由Android WebView的另一个方法可以解决,就是webView.loadUrl(url);。下面我们来讲讲如何实现异步回调。 在看异步回调这个问题之前我们可以先了解一下loadUrl可以做什么事情,一般情况下,加载url的时候我们会调用webView去加载传入参数url,但是它还有一个功能,就是执行Javascript方法,只需要传入String参数样式为:

javascript:try{ callbackFromNative(callbackParam);} catch(e){;}

看到这个传入参数,就可以想到,如果是Js端接收Native数据需要在根节点上添加一个方法:

function callbackFromNative(callbackParam){
  ...
  // 处理callbackFromNative逻辑
}

有了这样的一个方法我们就可以在Native端异步回调了。首先讲一下异步回调的业务逻辑: Js生成唯一的requestID -》 将回调参数callback方法及requestID存入本地Map中,入口参数和requestID传给Native->Native处理->Native新起UI线程loadUrl回调JS方法并回调之前的requestID和处理完成之后的返回参数-》Js方法根据Native回传的返回requestID找到存在callbackMap中的callback,将返回参数回调给callback。 其中有一点需要注意,一般情况下Native回调JS的时候返回的参数callbackParam为Base64后的JsonString,为什么要Base64呢?因为在执行loadUrl的时候不能有{}[]的存在,所以将回调参数callbackParam Base64后可以保证返回值不会被“方法注入”,到JS方法再解析Base64为Json就可以了。